/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.support.scripting.cmd;

import cn.easyplatform.EasyPlatformWithLabelKeyException;
import cn.easyplatform.ScriptRuntimeException;
import cn.easyplatform.dao.BizDao;
import cn.easyplatform.dao.EntityCallback;
import cn.easyplatform.dao.IdentityDao;
import cn.easyplatform.dos.FieldDo;
import cn.easyplatform.dos.UserDo;
import cn.easyplatform.entities.BaseEntity;
import cn.easyplatform.entities.beans.LogicBean;
import cn.easyplatform.i18n.I18N;
import cn.easyplatform.interceptor.CommandContext;
import cn.easyplatform.lang.Nums;
import cn.easyplatform.lang.Strings;
import cn.easyplatform.log.LogManager;
import cn.easyplatform.messages.vos.AuthorizationVo;
import cn.easyplatform.messages.vos.OrgVo;
import cn.easyplatform.messages.vos.h5.MessageVo;
import cn.easyplatform.messages.vos.h5.PushVo;
import cn.easyplatform.services.IProjectService;
import cn.easyplatform.services.ISessionManager;
import cn.easyplatform.services.ISubject;
import cn.easyplatform.spi.listener.event.AppEvent;
import cn.easyplatform.support.scripting.AbstractScriptCmd;
import cn.easyplatform.support.scripting.ScriptCmdContext;
import cn.easyplatform.support.scripting.cmd.MailBean.Attachment;
import cn.easyplatform.support.scripting.cmd.MailBean.Contact;
import cn.easyplatform.support.word.ReserveWordFactory;
import cn.easyplatform.type.*;
import cn.easyplatform.util.ConfigTools;
import cn.easyplatform.util.IdentityUtils;
import cn.easyplatform.util.RuntimeUtils;
import cn.easyplatform.utils.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.mail.EmailAttachment;
import org.apache.commons.mail.HtmlEmail;
import org.apache.commons.mail.MultiPartEmail;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.mail.internet.MimeUtility;
import java.io.Serializable;
import java.util.*;

import static cn.easyplatform.messages.vos.h5.MessageVo.*;

/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public class AppCmd extends AbstractScriptCmd {

    private final static String groupQuery = "SELECT b.userId FROM sys_user_group_info b,sys_group_info a where a.groupid=b.groupid and a.groupid=? and b.userId in (SELECT c.userId FROM sys_user_org_info d,sys_user_info c WHERE d.orgId = ? AND c.userId = d.userId AND c.state = 1)";

    private static final Logger log = LoggerFactory.getLogger(AppCmd.class);

    private final static ObjectMapper mapper = new ObjectMapper();

    /**
     * @param scc
     */
    AppCmd(ScriptCmdContext scc) {
        super(scc);
    }

    /**
     * 锁住应用
     */
    public void lock() {
        IProjectService ps = scc.getCommandContext().getProjectService();
        ps.setState(StateType.PAUSE);
    }

    /**
     * 解锁应用
     */
    public void unlock() {
        IProjectService ps = scc.getCommandContext().getProjectService();
        ps.setState(StateType.START);
    }

    /**
     * 是否在线
     */
    public boolean isOnline() {
        return scc.getCommandContext().getUser() != null && scc.getCommandContext().getUser().getState() == StateType.START;
    }

    /**
     * 判断用户是否在线
     *
     * @param userId
     */
    public boolean isOnline(String userId) {
        IProjectService ps = scc.getCommandContext().getProjectService();
        for (UserDo user : ps.getSessionManager().getUsers())
            if (user.getId().equals(userId))
                return true;
        return false;
    }

    /**
     * 获取指定主题的所有订阅者
     *
     * @param topic
     * @return
     */
    public String[] getSubscriber(String topic) {
        List<String> users = new ArrayList<>();
        IProjectService ps = scc.getCommandContext().getProjectService();
        for (UserDo user : ps.getSessionManager().getUsers()) {
            if (user.isSubscribed(topic))
                users.add(user.getId());
        }
        String[] result = new String[users.size()];
        users.toArray(result);
        return result;
    }

    /**
     * 获取在线用户
     *
     * @return
     */
    public String[] getOnlineUser() {
        List<String> as = new ArrayList<String>();
        IProjectService ps = scc.getCommandContext().getProjectService();
        for (UserDo user : ps.getSessionManager().getUsers()) {
            if (user.getType() < UserType.TYPE_OAUTH)
                as.add(user.getId());
        }
        return as.toArray(new String[as.size()]);
    }

    /**
     * 发送应用事件，例如列表的刷新、栏位的刷新等等
     *
     * @param name 事件名称，对应page参数消息主题
     * @param data 事件主体数据
     */
    public void publish(String name, Serializable data) {
        publish(Constants.EASYPLATFORM_TOPIC, name, data);
    }

    /**
     * 发送应用事件，例如列表的刷新、栏位的刷新等等
     *
     * @param topic 消息通道名称
     * @param name  事件名称，对应page参数消息主题
     * @param data  事件主体数据
     */
    public void publish(String topic, String name, Serializable data) {
        CommandContext cc = scc.getCommandContext();
        String[] toUsers = null;
        ISessionManager sm = cc.getProjectService().getSessionManager();
        // 通知所有在线用户
        Collection<UserDo> onlineUsers = sm.getUsers();
        toUsers = new String[onlineUsers.size()];
        int index = 0;
        for (UserDo user : onlineUsers) {
            if (user.isSubscribed(name))
                toUsers[index++] = user.getId();
        }
        if (toUsers.length > 0)
            cc.publish(topic, new AppEvent(name, data), toUsers);
    }

    /**
     * 发送消息
     *
     * @param topic
     * @param data
     */
    public void sendMessage(String topic, Serializable data, String... users) {
        CommandContext cc = scc.getCommandContext();
        ISessionManager sm = cc.getProjectService().getSessionManager();
        List<String> onlineUsers = new ArrayList<>();
        for (String user : users) {
            UserDo userDo = sm.getUser(user);
            if (userDo != null)
                onlineUsers.add(userDo.getId());
        }
        String[] toUsers = new String[onlineUsers.size()];
        onlineUsers.toArray(toUsers);
        scc.getCommandContext().sendMessage(topic, data, toUsers);
    }

    /**
     * 通知结束待办事项
     *
     * @param msgid
     * @param users
     */
    public void notify(long msgid, String... users) {
        if (msgid <= 0)
            throw new EasyPlatformWithLabelKeyException(
                    "script.engine.function.error", "#app.poll");
        CommandContext cc = scc.getCommandContext();
        BizDao dao = cc.getBizDao();
        List<FieldDo> params = new ArrayList<FieldDo>();
        params.add(new FieldDo(FieldType.INT, STATE_READED));
        params.add(new FieldDo(FieldType.LONG, msgid));
        params.add(new FieldDo(FieldType.VARCHAR, cc.getUser().getId()));
        dao.update(
                cc.getUser(),
                "update sys_notice_detail_info set status=? where msgid=? and touser=?",
                params, false);
        ISessionManager sm = cc.getProjectService().getSessionManager();
        String[] toUsers = null;
        if (users.length == 0) {
            // 通知所有在线用户
            Collection<UserDo> onlineUsers = sm.getUsers();
            toUsers = new String[onlineUsers.size()];
            int index = 0;
            for (UserDo user : onlineUsers) {
                if (user.getType() < UserType.TYPE_OAUTH)
                    toUsers[index++] = user.getId();
            }
            if (index != toUsers.length)
                toUsers = ArrayUtils.subarray(toUsers, 0, index);
        } else {
            List<String> onlineUsers = new ArrayList<>();
            for (String user : users) {
                UserDo userDo = sm.getUser(user);
                if (userDo != null)
                    onlineUsers.add(userDo.getId());
            }
            toUsers = new String[onlineUsers.size()];
            onlineUsers.toArray(toUsers);
        }
        if (toUsers.length > 0)
            cc.publish(Constants.EASYPLATFORM_TOPIC, new AppEvent(TYPE_TASK, -1), toUsers);
    }

    /**
     * 发布待办事项给指定的用户
     *
     * @param title
     * @param data
     * @param users
     */
    public long assign(String title, Serializable data, String... users) {
        if (users.length == 0)
            throw new EasyPlatformWithLabelKeyException(
                    "script.engine.function.error", "#app.assign(" + title + "....");
        try {
            return insertMessage(0, TYPE_TASK, title,
                    (data instanceof String ? (String) data : mapper.writeValueAsString(data)), users);
        } catch (JsonProcessingException ex) {
            throw new EasyPlatformWithLabelKeyException(
                    "script.engine.function.error", "#app.offer(" + title + "....");
        }
    }

    /**
     * 发布待办事项给指定的组
     *
     * @param title
     * @param data
     * @param groupid
     */
    public long assignGroup(String title, Serializable data, int groupid) {
        try {
            CommandContext cc = scc.getCommandContext();
            BizDao dao = cc.getBizDao();
            List<FieldDo> params = new ArrayList<FieldDo>();
            params.add(new FieldDo(FieldType.INT, groupid));
            params.add(new FieldDo(FieldType.VARCHAR, cc.getUser().getOrg()
                    .getId()));
            List<FieldDo[]> result = dao.selectList(groupQuery, params);
            long id = 0;
            if (!result.isEmpty()) {
                List<String> temp = new ArrayList<String>();
                for (FieldDo[] fd : result)
                    temp.add((String) fd[0].getValue());
                String[] users = new String[temp.size()];
                id = insertMessage(groupid, TYPE_TASK, title,
                        (data instanceof String ? (String) data : mapper.writeValueAsString(data)), users);
            }
            return id;
        } catch (JsonProcessingException ex) {
            throw new EasyPlatformWithLabelKeyException(
                    "script.engine.function.error", "#app.offer(" + title + "....");
        }
    }

    /**
     * 辅助方法，帮助创建指定类型的对象
     *
     * @param type
     * @return
     */
    public Object createBean(String type) {
        if ("bpm".equals(type))
            return new PushVo();
        if ("mail".equals(type))
            return new MailBean();
        return null;
    }

    /**
     * 仅发送消息,不保存
     *
     * @param content
     * @param users
     */
    public void broadcast(String content, String... users) {
        broadcast("info", content, users);
    }

    /**
     * 广播自定义类型的消息
     *
     * @param type    "info"|"warning"|"error"
     * @param content
     * @param users
     * @return
     */
    public void broadcast(String type, String content, String... users) {
        String[] toUsers = null;
        CommandContext cc = scc.getCommandContext();
        ISessionManager sm = cc.getProjectService().getSessionManager();
        if (users.length == 0) {
            // 通知所有在线用户
            Collection<UserDo> onlineUsers = sm.getUsers();
            toUsers = new String[onlineUsers.size()];
            int index = 0;
            for (UserDo user : onlineUsers) {
                if (user.getType() < UserType.TYPE_OAUTH)
                    toUsers[index++] = user.getId();
            }
            if (index != toUsers.length)
                toUsers = ArrayUtils.subarray(toUsers, 0, index);
        } else {
            List<String> onlineUsers = new ArrayList<>();
            for (String user : users) {
                UserDo userDo = sm.getUser(user);
                if (userDo != null)
                    onlineUsers.add(userDo.getId());
            }
            toUsers = new String[onlineUsers.size()];
            onlineUsers.toArray(toUsers);
        }
        if (toUsers.length > 0) {
            MessageVo msg = new MessageVo();
            msg.setFromUser(cc.getUser().getId());
            msg.setType(type);
            msg.setText(content);
            cc.publish(Constants.EASYPLATFORM_TOPIC, new AppEvent(TYPE_MESSAGE, msg), toUsers);
        }
    }

    /**
     * 发布系统消息
     *
     * @param title
     * @param content
     * @param users
     */
    public long notice(String title, String content, String... users) {
        return notice(TYPE_NOTICE, title, content, users);
    }

    /**
     * 发布自定义消息：例如新闻，公告
     *
     * @param type
     * @param title
     * @param content
     * @param users
     */
    public long notice(String type, String title, String content, String... users) {
        CommandContext cc = scc.getCommandContext();
        ISessionManager sm = cc.getProjectService().getSessionManager();
        if (users.length == 0) {
            // 如果没有指定用户，默认发给所有在线用户
            Collection<UserDo> onlineUsers = sm.getUsers();
            users = new String[onlineUsers.size()];
            int index = 0;
            for (UserDo user : onlineUsers) {
                if (user.getType() < UserType.TYPE_OAUTH)
                    users[index++] = user.getId();
            }
            if (index != users.length)
                users = ArrayUtils.subarray(users, 0, index);
        }
        return insertMessage(0, type, title, content, users);
    }

    /**
     * 发布系统消息给指定的组
     *
     * @param title
     * @param content
     * @param groupid
     */
    public long noticeGroup(String title, String content, int groupid) {
        return noticeGroup(TYPE_NOTICE, title, content, groupid);
    }

    /**
     * 发布自定义消息：例如新闻，公告 给指定的组
     *
     * @param type
     * @param title
     * @param content
     * @param groupid
     */
    public long noticeGroup(String type, String title, String content, int groupid) {
        CommandContext cc = scc.getCommandContext();
        BizDao dao = cc.getBizDao();
        List<FieldDo> params = new ArrayList<FieldDo>();
        params.add(new FieldDo(FieldType.INT, groupid));
        params.add(new FieldDo(FieldType.VARCHAR, cc.getUser().getOrg().getId()));
        List<FieldDo[]> result = dao.selectList(groupQuery, params);
        if (!result.isEmpty()) {
            List<String> temp = new ArrayList<String>();
            for (FieldDo[] fd : result)
                temp.add((String) fd[0].getValue());
            String[] users = new String[temp.size()];
            return insertMessage(0, type, title, content,
                    temp.toArray(users));
        }
        return 0;
    }

    private long insertMessage(int groupid, String type, String title,
                               String content, String[] users) {
        CommandContext cc = scc.getCommandContext();
        ISessionManager sm = cc.getProjectService().getSessionManager();
        String sql = "INSERT INTO sys_notice_info (sender,type,title,content,groupid,sendtime) VALUES (?,?,?,?,?,?)";
        BizDao dao = cc.getBizDao();
        long id = dao.insert(cc.getUser(), sql, false, cc.getUser().getId(), type, title, content, groupid, new Date());
        sql = "INSERT INTO sys_notice_detail_info (msgid,touser,status) VALUES (?,?,?)";
        List<String> onlineUsers = new ArrayList<>();
        for (String user : users) {
            dao.update(cc.getUser(), sql, false, id, user, MessageVo.STATE_UNREAD);
            UserDo userDo = sm.getUser(user);
            // 通知在线用户
            if (userDo != null)
                onlineUsers.add(userDo.getId());
        }
        if (!onlineUsers.isEmpty()) {
            String[] toUsers = new String[onlineUsers.size()];
            onlineUsers.toArray(toUsers);
            cc.publish(Constants.EASYPLATFORM_TOPIC, new AppEvent(type, 1), toUsers);
        }
        return id;
    }

    /**
     * 获取指定机构的所有子机构
     *
     * @param orgs
     * @return
     */
    public String[] getSUBS(String... orgs) {
        return getSub(true, false, orgs);
    }

    /**
     * 获取指定机构的所有子机构，包括本身
     *
     * @param orgs
     * @return
     */
    public String[] getSubs(String... orgs) {
        return getSub(true, true, orgs);
    }

    /**
     * 获取指定机构的直属子机构
     *
     * @param orgs
     * @return
     */
    public String[] getSUB(String... orgs) {
        return getSub(false, false, orgs);
    }

    /**
     * 获取指定机构的直属子机构,包括本身
     *
     * @param orgs
     * @return
     */
    public String[] getSub(String... orgs) {
        return getSub(false, true, orgs);
    }

    private String[] getSub(boolean isAll, boolean self, String... orgs) {
        CommandContext cc = scc.getCommandContext();
        String query = cc.getProjectService().getConfig().getOrgSubQuery();
        if (Strings.isBlank(query))
            return orgs;
        List<String> result = new ArrayList<String>();
        for (String orgId : orgs) {
            if (self)
                result.add(orgId);
            ReserveWordFactory.query(isAll, result, query, cc.getBizDao(),
                    orgId);
        }
        String[] data = new String[result.size()];
        result.toArray(data);
        return data;
    }

    /**
     * 发送邮件
     *
     * @param bean
     */
    public void sendMail(MailBean bean) {
        IProjectService ps = scc.getCommandContext().getProjectService();
        Map<String, String> section = ps.getConfig().getOptions("smtp");
        if (section == null)
            throw new EasyPlatformWithLabelKeyException(
                    "script.engine.cmd.stmp");
        if (Strings.isBlank(bean.getSubject()))
            throw new EasyPlatformWithLabelKeyException(
                    "script.engine.cmd.mail.subject");
        if (bean.getTo() == null)
            throw new EasyPlatformWithLabelKeyException(
                    "script.engine.cmd.mail.to");
        if (bean.getMsg() == null)
            throw new EasyPlatformWithLabelKeyException(
                    "script.engine.cmd.mail.msg");
        try {
            HtmlEmail email = new HtmlEmail();
            email.setSubject(bean.getSubject());
            email.setCharset(bean.getCharset() == null ? "UTF-8" : bean
                    .getCharset());
            email.setHtmlMsg(bean.getMsg());
            email.setSentDate(new Date());
            email.setHostName(section.get("host"));
            if ("true".equals(section.get("decrypt"))) {//还原密码
                email.setAuthentication(section.get("username"),
                        ConfigTools.decrypt(section.get("password")));
            } else
                email.setAuthentication(section.get("username"),
                        section.get("password"));
            email.setFrom(section.get("username"), section.get("sender"));
            if (section.get("ssl").equalsIgnoreCase("true")) {
                email.setSSLOnConnect(true);
                email.setSslSmtpPort(section.get("port"));
            } else
                email.setSmtpPort(Nums.toInt(section.get("port"), 25));
            for (Contact c : bean.getTo())
                email.addTo(c.getEmail(), c.getName());
            if (bean.getBcc() != null) {
                for (Contact c : bean.getBcc())
                    email.addBcc(c.getEmail(), c.getName());
            }
            if (bean.getCc() != null) {
                for (Contact c : bean.getCc())
                    email.addCc(c.getEmail(), c.getName());
            }
            if (bean.getReplyTo() != null) {
                for (Contact c : bean.getReplyTo())
                    email.addReplyTo(c.getEmail(), c.getName());
            }
            if (bean.getAttachments() != null) {
                for (Attachment attchment : bean.getAttachments()) {
                    EmailAttachment attachment = new EmailAttachment();
                    attachment.setDisposition(EmailAttachment.ATTACHMENT);
                    if (attchment.getDescription() != null)
                        attachment.setDescription(attchment.getDescription());
                    String filename = scc.getCommandContext().getRealPath(attchment.getPath());
                    attachment.setPath(filename);
                    attachment.setName(MimeUtility.encodeText(FilenameUtils
                            .getName(filename)));
                    ((MultiPartEmail) email).attach(attachment);
                }
            }
            email.send();
        } catch (Exception ex) {
            log.error("sendMail", ex);
            throw new EasyPlatformWithLabelKeyException(
                    "script.engine.cmd.mail.error", ex.getMessage());
        }
    }

    /**
     * 发送简单的邮件
     *
     * @param to
     * @param subject
     * @param msg
     */
    public void sendMail(String to, String subject, String msg) {
        MailBean mb = new MailBean();
        for (String toUser : to.split(","))
            mb.addTo(toUser);
        mb.setSubject(subject);
        mb.setMsg(msg);
        sendMail(mb);
    }

    /**
     * 计划执行某个参数（逻辑、功能)
     *
     * @param id
     * @param time
     */
    public long executeJob(String id, Object time, String... fields) {
        BaseEntity entity = scc.getCommandContext().getEntity(id);
        if (entity == null || !(entity instanceof LogicBean))
            throw new RuntimeException(I18N.getLabel("entity.not.found", EntityType.LOGIC.getName(), id));

        List<FieldDo> args = new ArrayList<>();
        if (fields.length > 0) {
            for (String field : fields) {
                args.add(scc.getTarget().getField(field));
            }
        } else {
            if (scc.getTarget().getData() != null && scc.getTarget().getData().getData() != null)
                args.addAll(scc.getTarget().getData().getData());
            args.addAll(scc.getTarget().getUserVars());
        }
        return scc.getCommandContext().getProjectService().getCustomJob().schedule((LogicBean) entity, time, args);
    }

    /**
     * 更新触发时间
     *
     * @param id
     * @param time
     * @return
     */
    public boolean modifyJob(Object id, Object time) {
        CommandContext cc = scc.getCommandContext();
        if (id instanceof Number) {
            return cc.getProjectService().getCustomJob().modify(((Number) id).longValue(), time);
        } else if (id instanceof String) {
            return cc.getEngineConfiguration().getScheduleService().modify(cc.getEnv().getId(), (String) id, time);
        }
        return false;
    }

    /**
     * 停止任务
     *
     * @param id
     */
    public void stopJob(Object id) {
        CommandContext cc = scc.getCommandContext();
        if (id instanceof Number) {
            cc.getProjectService().getCustomJob().stop(((Number) id).longValue());
        } else if (id instanceof String) {
            cc.getEngineConfiguration().getScheduleService().stop(cc.getEnv().getId(), (String) id);
        }
    }

    /**
     * 调用其它EP功能
     *
     * @param host
     * @param serviceId
     * @param orgId
     * @param nodeId
     * @param nodePass
     * @param taskId
     * @param data
     * @return 返回调用结果
     */
    public Object callEP(String host, String serviceId, String orgId, String nodeId, String nodePass, String taskId, Map<String, String> data) {
        Map<String, Object> params = new HashMap<>();
        params.put("serviceId", serviceId);
        params.put("orgId", orgId);
        params.put("nodeId", nodeId);
        params.put("nodePass", nodePass);
        params.put("id", taskId);
        params.put("data", data);
        if (log.isInfoEnabled())
            log.info("CallEP request : {}", params);
        Map<String, Object> resp = (Map<String, Object>) HttpUtil.post(host + "/api/execute", JSON.toJSONString(params));
        if (resp == null)
            throw new EasyPlatformWithLabelKeyException("api.call.error", host);
        if (log.isInfoEnabled())
            log.info("CallEP result : {}", resp);
        String code = (String) resp.get("code");
        if (code == null)
            throw new EasyPlatformWithLabelKeyException("api.call.code", host);
        Object body = resp.get("data");
        if (!"0000".equals(code))
            throw new ScriptRuntimeException(code, (String) body);
        return body;
    }

    /**
     * 获取自定义配置项
     *
     * @param group
     * @param name
     * @return
     */
    public String getOption(String group, String name) {
        return scc.getCommandContext().getProjectService().getConfig().getOption(group, name);
    }

    /**
     * 获取自定义配置项
     *
     * @param group
     * @return
     */
    public Object getOptions(String group) {
        return scc.getCommandContext().getProjectService().getConfig().getOptions(group);
    }

    /**
     * 重新加载配置项
     */
    public void loadOptions(String group) {
        scc.getCommandContext().getProjectService().getConfig().load(group);
    }

    /**
     * 获取工作空间路径
     *
     * @return
     */
    public String getWorkspace() {
        return FilenameUtils.normalize(scc.getCommandContext().getProjectService().getWorkPath());
    }

    /**
     * 获取工作空间路径
     *
     * @return
     */
    public String getWebWorkspace() {
        return FilenameUtils.normalize(scc.getCommandContext().getEngineConfiguration().getWebWorkspacePath() + scc.getCommandContext().getProjectService().getWorkspace());
    }

    /**
     * 获取web路径
     *
     * @return
     */
    public String getWebPath() {
        return FilenameUtils.normalize(scc.getCommandContext().getEngineConfiguration().getWebPath());
    }

    /**
     * 获取真实路径
     *
     * @param path
     * @return
     */
    public String getRealPath(String path) {
        return scc.getCommandContext().getRealPath(path);

    }

    /**
     * 第3方登陆，返回授权信息
     *
     * @param userId
     * @param ip
     * @return
     */
    public AuthorizationVo login(String userId, String ip) {
        return login(userId, ip, 0);
    }

    /**
     * 第3方登陆，返回授权信息
     *
     * @param userId
     * @param ip
     * @param timeToLive
     * @return
     */
    public AuthorizationVo login(String userId, String ip, int timeToLive) {
        Subject currentUser = org.apache.shiro.SecurityUtils.getSubject();
        CommandContext cc = scc.getCommandContext();
        if (cc.getUser().getType() < UserType.TYPE_OAUTH)
            throw new EasyPlatformWithLabelKeyException("api.login.error");
        IdentityDao dao = cc.getIdentityDao(true);
        UserDo userInfo = dao.getUser(cc.getProjectService().getConfig()
                .getAuthenticationQuery(), userId);
        if (userInfo != null) {
            EntityCallback<BaseEntity> cb = new EntityCallback<BaseEntity>() {
                @Override
                public BaseEntity getEntity(String entityId) {
                    return cc.getEntity(entityId);
                }

                public String getLabel(String code) {
                    return RuntimeUtils.getLabel(cc, code);
                }
            };
            List<OrgVo> orgs = dao.getUserOrgs(userId, cb);
            if (orgs.isEmpty())
                throw new EasyPlatformWithLabelKeyException("easyplatform.user.not.org", userId);
            ((ISubject) currentUser).setAuthenticate(true);
            userInfo.setId(userId);
            userInfo.setIp(ip);
            userInfo.setType(UserType.TYPE_EXCLUSIVE);
            userInfo.setLocale(cc.getEnv().getLocale());
            userInfo.setTimeout(timeToLive);
            userInfo.setLoginDate(new Date());
            userInfo.setLastAccessTime(new Date());
            userInfo.setState(StateType.START);
            cc.setUser(userInfo);
            AuthorizationVo av = IdentityUtils.getUserAuthorization(cc, userInfo, orgs.get(0).getId());
            IdentityUtils.log(cc, dao);
            LogManager.startUser(cc.getEngineConfiguration().getLogPath(), cc.getEnv().getId(), userInfo);
            //设置第3方登陆标志
            cc.set("$passport", av);
            return av;
        } else {
            throw new EasyPlatformWithLabelKeyException("easyplatform.user.not.found", userId);
        }
    }

    /**
     * 获取小程序用户的openId
     *
     * @param type
     * @param code
     * @return
     */
    public String getOpenId(String type, String code) {
        Map<String, String> options = scc.getCommandContext().getProjectService().getConfig().getOptions(type);
        if (options == null)
            return null;
        if (type.contains("wx")) {
            String url;
            if (type.contains("pub"))
                url = String.format("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", options.get("appid"), options.get("appsecret"), code);
            else
                url = String.format("https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code", options.get("appid"), options.get("appsecret"), code);
            Map<String, Object> jsonObject = (Map<String, Object>) HttpUtil.get(url);
            if (jsonObject == null)
                return null;
            if (jsonObject.get("openid") != null)
                return (String) jsonObject.get("openid");
            else
                return jsonObject.get("errcode") + ":" + jsonObject.get("errmsg");
        }
        return null;
    }

    /**
     * 设置会话属性
     *
     * @param name
     * @param value
     */
    public void put(String name, Object value) {
        scc.getCommandContext().set(name, value);
    }

    /**
     * 获取会话属性
     *
     * @param name
     * @return
     */
    public Object get(String name) {
        return scc.getCommandContext().get(name);
    }

    /**
     * 移除会话属性
     *
     * @param name
     */
    public void remove(String name) {
        scc.getCommandContext().remove(name);
    }
}
